package com.leenmvc.core.web.controller;

import com.leenmvc.core.annotation.ApiDescription;
import com.leenmvc.core.annotation.Note;
import com.leenmvc.core.base.BaseController;
import com.leenmvc.core.dao.communal.Wrapper;
import com.leenmvc.core.exception.BusinessException;
import com.leenmvc.core.security.User;
import com.leenmvc.core.security.dao.core.SysCaptchaDao;
import com.leenmvc.core.security.dao.core.SysUserTokenDao;
import com.leenmvc.core.security.entity.core.SysCaptcha;
import com.leenmvc.core.security.entity.core.SysUser;
import com.leenmvc.core.security.service.LoginService;
import com.leenmvc.core.security.service.core.SysUserCaptchaService;
import com.leenmvc.core.security.service.core.SysUserService;
import com.leenmvc.core.utils.StringUtils;
import com.leenmvc.core.utils.TipUtil;
import com.leenmvc.core.utils.dictionary.Dict;
import com.leenmvc.core.utils.security.PasswordUtils;
import com.leenmvc.core.utils.thread.ThreadLocalManager;
import com.leenmvc.core.utils.validator.ValidatorUtils;
import com.leenmvc.core.base.result.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;

/**
 * 登录控制
 *
 * @author leen
 * @since 2018/6/28 0028
 */
@RestController
@ApiDescription("登录控制")
public class LoginController extends BaseController<SysUser> {

    private static final Logger log = LoggerFactory.getLogger(LoginController.class);

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private LoginService loginService;

    @Autowired
    private SysCaptchaDao sysCaptchaDao;

    @Autowired
    private SysUserCaptchaService userCaptchaService;

    @Autowired
    private SysUserTokenDao sysUserTokenDao;

    /**
     * 用户登出
     *
     * @return
     */
    @PutMapping("/loginOut")
    @Note("登出操作只需要传递对应的header即可")
    public Result<SysUser> loginOut() {
        sysUserService.loginOut();
//        ThreadLocalManager.setUser(null);
        return new Result();
    }
    @GetMapping("captcha")
    @Note("获取本平台的验证码用于登录")
    public void captcha(HttpServletResponse response, String uuid) throws IOException {
        // uuid不能为空
        ValidatorUtils.notNull("uuid不能为空", uuid);
        if (uuid.length() > 255) {
            throw new BusinessException(TipUtil.getTip("LENGTH_VALIDATE", uuid));
        }
        // 生成图片验证码
        BufferedImage image = loginService.create(uuid);
        response.setHeader("Cache-Control", "no-store, no-cache");
        response.setContentType("image/jpeg");
        ServletOutputStream out = response.getOutputStream();
        ImageIO.write(image, "jpg", out);
        out.close();
    }

    /**
     * 用户软件的测试接口
     *
     * @return
     * @throws IOException
     */
    @GetMapping("testCaptcha")
    @Note("获取本平台的验证码用于登录(测试)")
    public Result getCaptcha() throws IOException {
        // uuid不能为空
        String uuid = StringUtils.getRandomString(5);

        // 生成图片验证码
        SysCaptcha captcha = loginService.createTestCaptcha(uuid);
        return new Result().ok(captcha);
    }

    /**
     * 登录操作
     *
     * @param username 用户名
     * @param password 密码
     * @param uuid     uuid
     * @param code     验证码
     * @return
     */
    @PostMapping("/loginUser")
    @Note("系统登录,输入用户名，密码，验证码")
    public Result login(@RequestParam(required = true) String username,
                        @RequestParam(required = true) String password,
                        @RequestParam(required = true) String uuid,
                        @RequestParam(required = true) String code) {
        SysUser user = null;
        // 判断登录方式
        if (StringUtils.isPhone(username)) {//手机号登录
            user = get("mobile", username);
        } else {
            user = get("username", username);
        }
        if (user == null) {
            // 加入日志信息
            throw new BusinessException("用户不存在");
        }

        if (!PasswordUtils.matches(password, user.getPassword())) {
            throw new BusinessException("密码错误");
        }
        // 账号停用
        if (user.getStatus() == 0) {
            throw new BusinessException("账号已停用");
        }

        String value = Dict.value("service_config", "captcha");
        // 标识是否开启验证码验证

        if ("1".equals(value)) {
            Wrapper wrapper = sysCaptchaDao.getQueryWrapper().eq("uuid", uuid).incField("code");
            ValidatorUtils.equals("验证码错误", code, sysCaptchaDao.getOneField(wrapper));
        }

        // 作废验证码
        if (!sysCaptchaDao.deleteById(uuid)) {
            throw new BusinessException("删除验证码失败！");
        }
        // 设置全局可用User
        ThreadLocalManager.setUser(user);
        String token = sysUserService.login(user);
        return new Result().ok(token);
    }

    /**
     * 注册操作
     *
     * @param sysUser 注册用户信息
     */
    @PostMapping("register")
    @Note("系统用户注册，注册用户信息")
    public Result register(@RequestBody SysUser sysUser) {
        sysUser.setSuperAdmin(0);
        sysUser.setStatus(0);
        sysUserService.insert(sysUser);
        return new Result();
    }

    @GetMapping("getUserInfo")
    @Note("获取用户信息，用于前端缓存")
    public Result getUserInfo() {
        return new Result().ok(User.getUser());
    }


    @GetMapping("getUserCaptcha")
    @Note("获取用户验证码,number 手机号或邮箱号，type 1手机号2邮箱,function 功能1修改密码2邮箱认证")
    public Result getUserCaptcha(@RequestParam String number, @RequestParam Integer type, @RequestParam Integer function) {
        userCaptchaService.sendCodeToDevice(number, type, function);
        return new Result();
    }

    @GetMapping("verifyCode")
    @Note("验证验证码，number 手机号或邮箱号，type 1手机号2邮箱，code 验证码")
    public Result verifyCode(@RequestParam String number, @RequestParam Integer type, @RequestParam String code) {
        int verifyCode = userCaptchaService.verifyCode(number, type, code);
        if (verifyCode == 0) {
            return new Result();
        } else if (verifyCode == 1) {
            return new Result().info("验证码输入错误");
        } else {
            return new Result().info("验证码已失效");
        }
    }

    @PutMapping("updatePasswd")
    @Note("修改密码，在验证验证码正确的情况下使用")
    public Result updatePasswd(@RequestParam String number, @RequestParam Integer type, @RequestParam String passwd, @RequestParam String code) {
        // 先验证验证码是否正确
        int verify = userCaptchaService.verifyCode(number, type, code);
        if (verify == 0) {
            loginService.updatePasswd(number, type, passwd);
            return new Result();
        } else if (verify == 1) {
            return new Result().info("验证码输入错误");
        } else {
            return new Result().info("验证码已失效");
        }
    }

    @PutMapping("passwordChange")
    @Note("登录之后修改自己的用户名和密码")
    public Result passwordChange(@RequestParam String oldPassword, @RequestParam String newPassword, @RequestParam String confirm) {
        if (!newPassword.equals(confirm)) {
            return new Result().info("确认密码和密码不一致，请检查！");
        }

        if (!PasswordUtils.matches(oldPassword, User.getPassword())) {
            return new Result().info("密码错误，请填写正确的用户密码！");
        }
        SysUser user = User.getUser();
        user.setPassword(PasswordUtils.encode(newPassword));
        sysUserService.update(user);
        return new Result();
    }

}
